///////////////////////////////////////////////////////////////////////
//
// NO_TypeDefinition.h
//
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
#ifndef NO_TypeDefinition_H
#define NO_TypeDefinition_H

///////////////////////////////////////////////////////////////////////
#include "NO_TypeID.h"

//////////////////////////////////////////////////////////////////////////
//
// Type creation
//
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define NO_BuildInType(T)		\
NO_TypeImp<T ,					\
NO_COMPOUND_TYPE,				\
NO_Sizing<T  >,					\
NO_Naming,						\
NO_Definition<T  >,				\
NO_ObjectReferencer<T  >,		\
NO_SimpleTransform<T  >,		\
NO_SingleConstructor,			\
NO_Copy<T  > >				

//////////////////////////////////////////////////////////////////////////
#define NO_PointerType(T)		\
NO_TypeImp<T *,					\
NO_POINTER_TYPE,				\
NO_Sizing<T *>,					\
NO_Naming,						\
NO_NoneDefinition,				\
NO_PointerReferencer<T  >,		\
NO_PointerTransform<T  >,		\
NO_SingleConstructor,			\
NO_Copy<T  > >					

//////////////////////////////////////////////////////////////////////////
#define NO_FuncType(T)			\
NO_TypeImp<T  ,					\
NO_COMPOUND_TYPE,				\
NO_Sizing<T  >,					\
NO_Naming,						\
NO_NoneDefinition,				\
NO_ObjectReferencer<T  >,		\
NO_FuncPointerTransform<T  >,	\
NO_NoneConstructors,			\
NO_Copy<T  > >				

//////////////////////////////////////////////////////////////////////////
#define NO_ObjectType(T)		\
NO_TypeImp<T ,					\
NO_OBJECT_TYPE,					\
NO_Sizing<T  >,					\
NO_Naming,						\
NO_Definition<T  >,				\
NO_ObjectReferencer<T  >,		\
NO_ObjectTransform<T  >,		\
NO_SingleConstructor >			

//////////////////////////////////////////////////////////////////////////
#define NO_PairType(K,V)				\
NO_TypeImp<std::pair<K,V >,				\
NO_COMPOUND_TYPE,						\
NO_Sizing<std::pair<K,V > >,			\
NO_Naming,								\
NO_NoneDefinition,						\
NO_ObjectReferencer<std::pair<K,V > >,	\
NO_PairTransform<K,V >,					\
NO_SingleConstructor,					\
NO_Copy<std::pair<K,V > > >				

//////////////////////////////////////////////////////////////////////////
#define NO_VectorType(V)						\
NO_TypeImp<std::vector<V > ,					\
NO_COMPOUND_TYPE,								\
NO_Sizing<std::vector<V > >,					\
NO_Naming,										\
NO_NoneDefinition,								\
NO_ObjectReferencer<std::vector<V > >,			\
NO_ContainerTransform<std::vector<V > ,V >,		\
NO_SingleConstructor,							\
NO_Copy<std::vector<V > > >						

//////////////////////////////////////////////////////////////////////////
#define NO_MapType(K,V)									\
NO_TypeImp<std::map<K,V > ,									\
NO_COMPOUND_TYPE,											\
NO_Sizing<std::map<K,V > >,									\
NO_Naming,													\
NO_NoneDefinition,											\
NO_ObjectReferencer<std::map<K,V > >,						\
NO_ContainerTransform<std::map<K,V > ,std::pair<K,V > >,	\
NO_SingleConstructor,										\
NO_Copy<std::map<K,V > > >									

//////////////////////////////////////////////////////////////////////////
#define NO_PODType(T)		\
NO_TypeImp<T  ,				\
NO_COMPOUND_TYPE,			\
NO_Sizing<T  >,				\
NO_Naming,					\
NO_Definition<T  >,			\
NO_ObjectReferencer<T  >,	\
NO_ClassTransform<T  >,		\
NO_SingleConstructor,		\
NO_Copy<T  >,				\
NO_MemberList>				

//////////////////////////////////////////////////////////////////////////
#define NO_InterfaceType(T)	\
NO_TypeImp<T  ,					\
NO_COMPOUND_TYPE,				\
NO_Sizing<T  >,					\
NO_Naming,						\
NO_Definition<T  >,				\
NO_NoneReferencer,				\
NO_ClassTransform<T >,			\
NO_SingleConstructor,			\
NO_NoneCopy ,					\
NO_MemberList,					\
NO_FunctionList>				

//////////////////////////////////////////////////////////////////////////
#define NO_SimpleType(T)	\
NO_TypeImp<T  ,				\
NO_COMPOUND_TYPE,			\
NO_Sizing<T  >,				\
NO_Naming,					\
NO_Definition<T  >,			\
NO_ObjectReferencer<T  >,	\
NO_ClassTransform<T  >,		\
NO_SingleConstructor,		\
NO_Copy<T  >,				\
NO_MemberList,				\
NO_FunctionList>				

//////////////////////////////////////////////////////////////////////////
#define NO_NCSimpleType(T)	\
NO_TypeImp<T  ,				\
NO_COMPOUND_TYPE,			\
NO_Sizing<T  >,				\
NO_Naming,					\
NO_Definition<T  >,			\
NO_ObjectReferencer<T  >,	\
NO_ClassTransform<T  >,		\
NO_SingleConstructor,		\
NO_NoneCopy,				\
NO_MemberList,				\
NO_FunctionList,			\
NO_BaseList>						

//////////////////////////////////////////////////////////////////////////
#define NO_DerivedType(T)	\
NO_TypeImp<T ,				\
NO_COMPOUND_TYPE,			\
NO_Sizing<T  >,				\
NO_Naming,					\
NO_Definition<T >,			\
NO_ObjectReferencer<T >,	\
NO_ClassTransform<T >,		\
NO_SingleConstructor,		\
NO_Copy<T >,				\
NO_MemberList,				\
NO_FunctionList,			\
NO_BaseList>

//////////////////////////////////////////////////////////////////////////
#define NO_FullType(T)	\
NO_TypeImp<T ,			\
NO_COMPOUND_TYPE,		\
NO_Sizing<T >,			\
NO_Naming,				\
NO_Definition<T >,		\
NO_ObjectReferencer<T >,	\
NO_ClassTransform<T >,	\
NO_ConstructorList,		\
NO_Copy<T >,			\
NO_MemberList,			\
NO_FunctionList,		\
NO_BaseList>					

//////////////////////////////////////////////////////////////////////////
// 
// base creation
// 
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define noMakeBase(B,D) new NO_Base<B ,D >()

//////////////////////////////////////////////////////////////////////////
// 
// Constructor creation
// 
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define noMakeConstructor(T) new NO_Constructor<T >()

//////////////////////////////////////////////////////////////////////////
// 
// Member creation
// 
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class M, class C> 
NO_IMember* noMakeMember(M C::* m, const NO_Int8* n)
{
	return new NO_Member<M,C >(m,n);
}

//////////////////////////////////////////////////////////////////////////
template<class M> 
NO_IMember* noMakeMember(M* m, const NO_Int8* n)
{
	return new NO_StaticMember<M >(m,n);
}

//////////////////////////////////////////////////////////////////////////
template<class U, NO_UInt32 N, class C, class M>
NO_IMember* noMakeRange(M C::*m, const NO_Int8* n)
{
	typedef U MT[N] ;
	MT C::* p = m;
	return new NO_RangeMember<U,N,C >(m,n);
}

//////////////////////////////////////////////////////////////////////////
template<class U, NO_UInt32 N, class M>
NO_IMember* noMakeRange(M* m, const NO_Int8* n)
{
	typedef U MT[N] ;
	MT* p = m;
	return new NO_StaticRangeMember<U,N >(*m,n);
}

//////////////////////////////////////////////////////////////////////////
// 
// function creation
// 
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define RETTYPE			typename fastdelegate::detail::VoidToDefaultVoid<R>::type
#define RETTYPE_UNDECO  typename fastdelegate::detail::VoidToDefaultVoid<UnR>::type

//////////////////////////////////////////////////////////////////////////
struct NO_EmptyClass {};

//////////////////////////////////////////////////////////////////////////
// N=0
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class R, class O = NO_EmptyClass>	
struct NO_FunctionHelperV
{
	typedef NO_MemFunc0<fastdelegate::FastDelegate0<RETTYPE>, 
		R (O::*)(void)const, O, RETTYPE_UNDECO> Const; 

	typedef NO_MemFunc0<fastdelegate::FastDelegate0<RETTYPE>, 
		R (O::*)(void), O, RETTYPE_UNDECO> Member;

	typedef NO_Func0<fastdelegate::FastDelegate0<RETTYPE>, 
		R (*)(void), RETTYPE_UNDECO> Static;
};

//////////////////////////////////////////////////////////////////////////
template<class R, class O>	
typename NO_FunctionHelperV<R,R,O>::Member* 
noMakeFunc0(R(O::*f)(void), const NO_Int8* n)
{return new NO_FunctionHelperV<R,R,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R, class O>
typename NO_FunctionHelperV<R,R,O>::Const* 
noMakeFunc0(R(O::*f)(void)const, const NO_Int8* n)	
{return new NO_FunctionHelperV<R,R,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R>			
typename NO_FunctionHelperV<R,R>::Static* 
noMakeFunc0(R(*f)(void), const NO_Int8* n)	 
{return new NO_FunctionHelperV<R,R>::Static(f,n);}

//////////////////////////////////////////////////////////////////////////
// for functions with reference parameter or return type
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class R, class O>	
typename NO_FunctionHelperV<UnR,R,O>::Member* 
noMakeFunc0Ref(R(O::*f)(void), const NO_Int8* n)	
{return new NO_FunctionHelperV<UnR,R,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class R, class O>	
typename NO_FunctionHelperV<UnR,R,O>::Const* 
noMakeFunc0Ref(R(O::*f)(void)const, const NO_Int8* n)
{return new NO_FunctionHelperV<UnR,R,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class R>			
typename NO_FunctionHelperV<UnR,R>::Static* 
noMakeFunc0Ref(R(*f)(void), const NO_Int8* n)	
{return new NO_FunctionHelperV<UnR,R>::Static(f,n);}

//////////////////////////////////////////////////////////////////////////
// N=1
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class R, class P1, class O = NO_EmptyClass >	
struct NO_FunctionHelper1P
{
	typedef NO_MemFunc1<fastdelegate::FastDelegate1<P1,RETTYPE>, 
		R (O::*)(P1)const, UnP1, O, RETTYPE_UNDECO> Const; 

	typedef NO_MemFunc1<fastdelegate::FastDelegate1<P1,RETTYPE>, 
		R (O::*)(P1), UnP1, O, RETTYPE_UNDECO> Member;

	typedef NO_Func1<fastdelegate::FastDelegate1<P1,RETTYPE>, 
		R (*)(P1), UnP1, RETTYPE_UNDECO> Static;
};

//////////////////////////////////////////////////////////////////////////
template<class R, class O, class P1>
typename NO_FunctionHelper1P<R,P1,R,P1,O>::Member* 
noMakeFunc1(R(O::*f)(P1), const NO_Int8* n)	
{return new NO_FunctionHelper1P<R,P1,R,P1,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R, class O, class P1>
typename NO_FunctionHelper1P<R,P1,R,P1,O>::Const* 
noMakeFunc1(R(O::*f)(P1)const, const NO_Int8* n)	
{return new NO_FunctionHelper1P<R,P1,R,P1,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R, class P1>	
typename NO_FunctionHelper1P<R,P1,R,P1>::Static* 
noMakeFunc1(R(*f)(P1), const NO_Int8* n)		
{return new NO_FunctionHelper1P<R,P1,R,P1>::Static(f,n);}

//////////////////////////////////////////////////////////////////////////
// for functions with reference parameter or return type
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class R, class P1, class O>
typename NO_FunctionHelper1P<UnR,UnP1,R,P1,O>::Member*
noMakeFunc1Ref(R(O::*f)(P1), const NO_Int8* n)
{return new NO_FunctionHelper1P<UnR,UnP1,R,P1,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class R, class P1, class O> 
typename NO_FunctionHelper1P<UnR,UnP1,R,P1,O>::Const*
noMakeFunc1Ref(R(O::*f)(P1)const, const NO_Int8* n)
{return new NO_FunctionHelper1P<UnR,UnP1,R,P1,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class R, class P1>			
typename NO_FunctionHelper1P<UnR,UnP1,R,P1>::Static* 
noMakeFunc1Ref(R(*f)(P1), const NO_Int8* n)
{return new NO_FunctionHelper1P<UnR,UnP1,R,P1>::Static(f,n);}

//////////////////////////////////////////////////////////////////////////
// N=2
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class UnP2, 
		 class R,   class P1,   class P2, 
		 class O = NO_EmptyClass >	
struct NO_FunctionHelper2P
{
	typedef NO_MemFunc2<fastdelegate::FastDelegate2<P1,P2,RETTYPE>, 
		R (O::*)(P1,P2)const, UnP1, UnP2, O, RETTYPE_UNDECO> Const; 

	typedef NO_MemFunc2<fastdelegate::FastDelegate2<P1,P2,RETTYPE>, 
		R (O::*)(P1,P2), UnP1, UnP2, O, RETTYPE_UNDECO> Member;

	typedef NO_Func2<fastdelegate::FastDelegate2<P1,P2,RETTYPE>, 
		R (*)(P1,P2), UnP1, UnP2, RETTYPE_UNDECO> Static;
};

//////////////////////////////////////////////////////////////////////////
template<class R, class P1, class P2, class O>	
typename NO_FunctionHelper2P<R,P1,P2,R,P1,P2,O>::Member*
noMakeFunc2(R(O::*f)(P1,P2), const NO_Int8* n)
{return new NO_FunctionHelper2P<R,P1,P2,R,P1,P2,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R, class P1, class P2, class O>	
typename NO_FunctionHelper2P<R,P1,P2,R,P1,P2,O>::Const*
noMakeFunc2(R(O::*f)(P1,P2)const, const NO_Int8* n)	
{return new NO_FunctionHelper2P<R,P1,P2,R,P1,P2,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class R, class P1, class P2>			
typename NO_FunctionHelper2P<R,P1,P2,R,P1,P2>::Static*
noMakeFunc2(R(*f)(P1,P2), const NO_Int8* n)	
{return new NO_FunctionHelper2P<R,P1,P2,R,P1,P2>::Static(f,n);}

//////////////////////////////////////////////////////////////////////////
// for functions with reference parameter or return type
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class UnP2, class R, class P1, class P2, class O> 
typename NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2,O>::Member*
noMakeFunc2Ref(R(O::*f)(P1,P2), const NO_Int8* n)	
{return new NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2,O>::Member(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class UnP2, class R, class P1, class P2, class O> 
typename NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2,O>::Const*
noMakeFunc2Ref(R(O::*f)(P1,P2)const, const NO_Int8* n)	
{return new NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2,O>::Const(f,n);}

//////////////////////////////////////////////////////////////////////////
template<class UnR, class UnP1, class UnP2, class R, class P1, class P2>		  
typename NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2>::Static*
noMakeFunc2Ref(R(*f)(P1,P2), const NO_Int8* n)
{return new NO_FunctionHelper2P<UnR,UnP1,UnP2,R,P1,P2>::Static(f,n);}

#endif